package world.snowcrystal.service;


import org.redisson.api.RFuture;
import world.snowcrystal.dto.ChatroomMessage;
import world.snowcrystal.dto.ChatroomUser;
import world.snowcrystal.exception.SnowcrystalAlreadyExistException;

import java.util.Collection;
import java.util.List;
import java.util.concurrent.Future;

public interface ChatroomService {

    /**
     * 获取当前聊天室在线人数，包括所有匿名用户在内
     * @return long 并非 100% 保证正确
     * @since 1.0
     * @author tianqing
     */
    int getOnlineUsers();

    Future<Integer> getOnlineUsersAsync();

    /**
     * 获取聊天室最近的聊天记录
     * @return {@link List} 最近的聊天记录
     * @since 1.0
     * @author tianqing
     */
    Collection<ChatroomMessage> getAllRecentMessages();

    RFuture<List<ChatroomMessage>> getAllRecentMessagesAsync();

    /**
     * 获取最近的 n 条记录
     *
     * @author tianqing
     * @since 1.0
     */
    Collection<ChatroomMessage> getRecentMessages(int offset, int n);


    RFuture<List<ChatroomMessage>> getRecentMessagesAsync(int offset, int n);


    /**
     * 上传新的消息到缓存服务器
     * @param msg 聊天室对象实例
     * @since 1.0
     * @author tianqing
     * @return 如果上传成功，则返回 <code>true</code>，否则其他情况返回 <code>false</code>
     */
    boolean addNewMessage(ChatroomMessage msg);


    Future<Boolean> addNewMessageAsync(ChatroomMessage msg);


    /**
     * 获取聊天室当前的消息数量，不保证一定准确，因为存在延迟清除机制
     * @since 1.0
     * @author tianqing
     */
    int cachedMessageNumber();


    /**
     * 添加一个用户表示到缓存服务器；实现需要设置一个较短的过期时间
     * 当添加的用户已经存在时，不要做任何事。
     * <p>当用户数据过期，也算作不存在，实现需要手动清理一下过期的数据</p>
     * @param user 聊天室的用户表示
     * @param overwrite 如果用户已经存在，是否进行覆盖
     * @return 如果添加成功，则返回 true，否则因为网络或其他非唯一性问题使得用户添加失败，则返回 false
     * @throws SnowcrystalAlreadyExistException 用户已经存在并且 <code>overwrite</code>为 <code>false</code> 而导致的添加失败
     * @since 1.0
     * @author tianqing
     */
    boolean addOnlineChatroomUser(ChatroomUser user,boolean overwrite)
            throws SnowcrystalAlreadyExistException;

    /**
     * <code>overwrite</code> 为 <code>false</code> 的 {@link #addOnlineChatroomUser(ChatroomUser, boolean)}
     * @see #addOnlineChatroomUser(ChatroomUser, boolean)
     * @since 1.0
     * @author tianqing
     */
    boolean addOnlineChatroomUser(ChatroomUser user) throws SnowcrystalAlreadyExistException;

    /**
     * 这可能需要遍历整个缓存来查找这个用户是否已经登录
     * @return 如果用户已经存在，则返回 true，否则返回 false
     * @since 1.0
     * @author tianqing
     */
    boolean checkUserExistence(String id);

    /**
     * 检查用户是否已经使用某个设备登录了
     * @return 如果这个用户已经使用 fp 表示的设备登录，则返回 true
     */
    boolean checkUserExistence(String fp,String id);

    /**
     * 为匿名用户产生一个唯一标识；调用者需要在生成后
     * 检查缓存数据库中是否存在同样的标识，有则重新调用该函数生成；
     * 指导生成的标识具有唯一性；实现可以使用保证唯一性的生成算法来避免这种情况发生.
     * @since 1.0
     * @author tianqing
     */
    String generateChatroomUserId();


    /**
     * 刷新用户数据的 ttl；如果成功则返回 true，否则，如果用户数据已经过期，
     * 或者用户数据不存在，返回 false
     * @since 1.0
     * @author tianqing
     */
    boolean refreshUserExpiration(String fp);


    /**
     * 检查聊天室中是否已经存在某个设备
     * @param fp 设备指纹
     * @return true 如果存在，否则返回 false
     * @since 1.0
     * @author tianqing
     */
    boolean checkDeviceExistence(String fp);

    /**
     * 根据设备指纹获取聊天室用户的表示，如果不存在，则返回 null
     * @since 1.0
     * @author tianqing
     */
    ChatroomUser getChatroomUser(String fp);

    /**
     * 根据用户 id 获取所有其在聊天室的表示，每一个表示代表了这个用户的不同设备
     * @param id 用户 id
     * @return 如果该指定的 id 不存在，则返回 null
     */
    List<ChatroomUser> retrieveChatroomUsers(String id);


    void deleteChatroomUser(String fp);

}
